package com.controller;


import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.UsersEntity;
import com.service.TokenService;
import com.service.UsersService;
import com.utils.MPUtil;
import com.utils.PageUtils;
import com.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Map;

/**
 * 用户管理
 * 前端接口
 */
@RequestMapping("users")
@RestController
public class UsersController {

    @Autowired
    private UsersService usersService;

    @Autowired
    private TokenService tokenService;

    /**
     * 登录接口
     * 该方法用于用户登录，验证用户名、密码和验证码的正确性，并生成登录令牌
     * 使用了IgnoreAuth注解，表示该方法不受权限控制，任何用户均可尝试访问
     * @param username 用户名，用于识别用户
     * @param password 用户输入的密码，用于验证用户身份
     * @param captcha  验证码，用于防止自动化攻击
     * @param request  HTTP请求对象，用于获取会话信息
     * @return 返回一个包含登录结果、令牌和用户角色及ID的响应对象
     */
    @IgnoreAuth
    @PostMapping(value = "/login")
    public R login(String username, String password, String captcha, HttpServletRequest request) {
        // 根据用户名查询数据库中的用户信息
        UsersEntity user = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", username));
        // 验证用户名和密码的正确性
        if (user == null || !user.getPassword().equals(password)) {
            return R.error("账号或密码不正确");
        }
        // 生成用户登录令牌
        String token = tokenService.generateToken(user.getId(), username, "users", user.getRole());
        // 创建成功响应对象，并添加登录令牌、用户角色和用户ID信息
        R r = R.ok();
        r.put("token", token);
        r.put("role", user.getRole());
        r.put("userId", user.getId());
        // 返回包含登录信息的响应对象
        return r;
    }


    /**
     * 用户注册接口
     * 此接口允许用户通过POST请求注册新账户。它会首先检查用户名是否已被占用，
     * 如果用户名已存在，则返回错误信息。否则，将用户信息插入数据库，并返回成功信息。
     * @param user 用户实体对象，包含用户名等注册信息
     * @return R 返回结果，包含注册成功或失败的信息
     */
    @IgnoreAuth
    @PostMapping(value = "/register")
    public R register(@RequestBody UsersEntity user) {
        // 验证用户实体的合法性
        // ValidatorUtils.validateEntity(user);
        // 检查用户名是否已存在
        if (usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", user.getUsername())) != null) {
            return R.error("用户已存在");
        }
        // 插入新用户到数据库
        usersService.insert(user);
        // 返回注册成功信息
        return R.ok();
    }


    /**
     * 实现用户退出功能
     * 通过调用此方法，使当前用户的session失效，实现退出功能
     * @param request HTTP请求对象，用于获取session
     * @return 返回一个R对象，表示退出结果
     */
    @GetMapping(value = "logout")
    public R logout(HttpServletRequest request) {
        // 使session失效，实现用户退出
        request.getSession().invalidate();
        // 返回退出成功的消息
        return R.ok("退出成功");
    }


    /**
     * 密码重置
     * 提供密码重置功能，将指定用户名的用户密码重置为默认值
     * @param username 用户名，标识需要重置密码的用户
     * @param request  HTTP请求对象，用于获取请求信息（此处未具体使用）
     * @return 如果账号不存在，返回错误信息"账号不存在"；否则，将密码重置为"123456"并返回成功信息"密码已重置为：123456"
     */
    @IgnoreAuth
    @RequestMapping(value = "/resetPass")
    public R resetPass(String username, HttpServletRequest request) {
        // 根据用户名查询用户信息
        UsersEntity user = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", username));
        // 如果未找到用户，则返回错误提示
        if (user == null) {
            return R.error("账号不存在");
        }
        // 将用户密码重置为默认值"123456"
        user.setPassword("123456");
        // 更新用户信息
        usersService.update(user, null);
        // 返回密码重置成功的提示
        return R.ok("密码已重置为：123456");
    }


    /**
     * 用户列表页面查询接口
     * 通过分页查询用户列表，并根据请求参数对查询结果进行排序和条件筛选
     * 主要用于展示用户列表数据，可以指定分页参数和排序规则，支持模糊查询和区间查询
     * @param params 请求参数，通常包含分页信息和排序规则
     * @param user   用户实体对象，用于模糊查询的条件
     * @return 返回分页查询结果，包含用户列表和分页信息
     */
    @RequestMapping("/page")
    public R page(@RequestParam Map<String, Object> params, UsersEntity user) {
        // 创建用户实体的查询包装器
        EntityWrapper<UsersEntity> ew = new EntityWrapper<UsersEntity>();
        // 执行分页查询，并应用排序和条件筛选
        PageUtils page = usersService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params));
        // 返回查询结果，将分页数据封装到响应对象中
        return R.ok().put("data", page);
    }


    /**
     * 用户列表页面的处理方法
     * 该方法用于处理用户列表的请求，返回用户列表数据
     * @param user 用户实体对象，用于接收查询参数
     * @return 返回一个Result对象，其中包含用户列表数据
     */
    @RequestMapping("/list")
    public R list(UsersEntity user) {
        // 创建查询条件封装对象
        EntityWrapper<UsersEntity> ew = new EntityWrapper<UsersEntity>();
        // 设置查询条件，使用MPUtil工具类生成查询参数映射
        ew.allEq(MPUtil.allEQMapPre(user, "user"));
        // 返回成功的结果，其中data字段包含用户列表数据
        return R.ok().put("data", usersService.selectListView(ew));
    }


    /**
     * 获取用户信息
     * 通过用户ID获取用户详细信息的接口此接口假设用户ID作为路径变量，
     * 并通过用户服务查询数据库以检索用户信息返回的响应包含一个用户实体，
     * 其中包含所请求用户的所有相关信息
     * @param id 用户ID，用于标识要获取信息的用户
     * @return 返回包含用户信息的响应对象，包括用户的所有详细信息
     */
    @RequestMapping("/info/{id}")
    public R info(@PathVariable("id") String id) {
        UsersEntity user = usersService.selectById(id);
        return R.ok().put("data", user);
    }


    /**
     * 获取用户的session信息
     * 通过HttpServletRequest获取当前用户的session，并从session中提取用户ID，
     * 然后调用用户服务根据ID查询用户信息，最后将查询到的用户信息返回。
     */
    @RequestMapping("/session")
    public R getCurrUser(HttpServletRequest request) {
        // 从session中获取用户ID
        Integer id = (Integer) request.getSession().getAttribute("userId");
        // 根据用户ID查询用户信息
        UsersEntity user = usersService.selectById(id);
        // 将查询到的用户信息放入返回对象，并返回成功响应
        return R.ok().put("data", user);
    }


    /**
     * 保存用户信息
     * 该方法用于保存（插入）用户信息到数据库。它首先检查数据库中是否已存在相同用户名的用户，
     * 如果存在，则返回错误信息。如果用户名可用，它将设置用户的默认密码并插入用户数据。
     * @param user 用户对象，包含要保存的用户信息
     * @return R 插入操作的结果，如果用户已存在则返回错误信息，否则返回成功信息
     */
    @PostMapping("/save")
    public R save(@RequestBody UsersEntity user) {
//    	ValidatorUtils.validateEntity(user); // 校验用户对象的合法性
        if (usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", user.getUsername())) != null) {
            return R.error("用户已存在");
        }
        user.setPassword("123456"); // 设置默认密码
        usersService.insert(user);
        return R.ok();
    }


    /**
     * 更新用户信息
     * @param user 要更新的用户对象，包含需要修改的用户信息
     * @return R 返回操作结果，OK表示操作成功
     */
    @RequestMapping("/update")
    public R update(@RequestBody UsersEntity user) {
//        ValidatorUtils.validateEntity(user); // 校验用户对象的合法性
        usersService.updateById(user);//根据用户ID进行全部字段的更新操作
        return R.ok(); // 返回操作成功的结果
    }


    /**
     * 删除
     * 通过接收一组用户ID，批量删除用户信息。
     * 该方法使用了@RequestBody注解，表示请求体中的数据会被解析为方法的参数。
     * 使用@RequestBody接收数据时，客户端需要发送JSON格式的数据，对应到Java对象。
     * 在这种情况下，客户端发送的JSON数据应包含一个名为ids的Long数组。
     * 例如：{"ids":[1,2,3]}
     * @param ids 用户ID数组，表示需要删除的用户ID列表。
     * @return 删除操作的结果，使用R对象封装，表示操作的状态。
     */
    @RequestMapping("/delete")
    public R delete(@RequestBody Long[] ids) {
        usersService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    }

}
